package org.com.yz.dubbo.web.core;

import org.com.yz.dal.dao.model.ChineseCalendaInfo;
import org.com.yz.dubbo.web.service.CheckMchAccntService;
import org.com.yz.dubbo.web.service.ChineseCalendaInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @ClassName ChineseCalendar
 * @Author wzc
 * @Date 2018/9/25 15:59
 * * 获取当年中国的法定节假日和工作日等信息。 如下是当前包含的功能：
 * * 01-给定日期，判断是否是法定节假日。
 * * 02-给定日期，判断是否是周末（周末不一定是休息日，可能需要补班）。
 * * 03-给定日期，判断是否是需要额外补班的周末。
 * * 04-给定日期，判断是否是休息日（包含法定节假日和不需要补班的周末）。
 * * 05-给定日期，判断是否是工作日(非休息日)。
 * * 06-获取一年中总共的天数。
 * * 07-获取一年中法定节假日的天数。
 * * 08-获取一年中需要补班的周末天数。
 * * 09-获取一年中周末的天数（周六+周日）。
 * * 10-获取一年中休息日的天数（法定节假日+不需要补班的周末）。
 **/
@Component
public class ChineseCalendar {

    @Autowired
    private ChineseCalendaInfoService chineseCalendaInfoService;

    @PostConstruct //通过@PostConstruct实现初始化bean之前进行的操作
    public void init() {
       // System.out.print("哦开裆裤");
       // chineseCalendar = this;
        //chineseCalendar.chineseCalendaInfoService = this.chineseCalendaInfoService;
        // 初使化时将已静态化的testService实例化


    }


        // 法律规定的放假日期
    private  static  List<String> lawHolidays = new ArrayList<String>(Arrays.asList( ));
    // 由于放假需要额外工作的周末
    private  static List<String> extraWorkdays = new ArrayList<String>(Arrays.asList( ));

    /**
     * 判断是否是法定假日
     *
     * @param calendar
     * @return
     * @throws Exception
     */
    public boolean isLawHoliday(String calendar) throws Exception {
        this.isMatchDateFormat(calendar);
        if (lawHolidays.contains(calendar)) {
            return true;
        }
        return false;
    }

    /**
     * 判断是否是周末
     *
     * @param calendar
     * @return
     */
    public boolean isWeekends(String calendar) throws Exception {
        this.isMatchDateFormat(calendar);
        // 先将字符串类型的日期转换为Calendar类型
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date date = sdf.parse(calendar);
        Calendar ca = Calendar.getInstance( );
        ca.setTime(date);
        if (ca.get(Calendar.DAY_OF_WEEK) == 1
                || ca.get(Calendar.DAY_OF_WEEK) == 7) {
            return true;
        }
        return false;
    }

    /**
     * 判断是否是需要额外补班的周末
     *
     * @param calendar
     * @return
     * @throws Exception
     */
    public boolean isExtraWorkday(String calendar) throws Exception {
        this.isMatchDateFormat(calendar);
        if (extraWorkdays.contains(calendar)) {
            return true;
        }
        return false;
    }

    /**
     * 判断是否是休息日（包含法定节假日和不需要补班的周末）
     *
     * @param calendar
     * @return
     * @throws Exception
     */
    public boolean isHoliday(String calendar) throws Exception {
        this.isMatchDateFormat(calendar);
        // 首先法定节假日必定是休息日
        if (this.isLawHoliday(calendar)) {
            return true;
        }
        // 排除法定节假日外的非周末必定是工作日
        if (!this.isWeekends(calendar)) {
            return false;
        }
        // 所有周末中只有非补班的才是休息日
        if (this.isExtraWorkday(calendar)) {
            return false;
        }
        return true;
    }

    /**
     * 判断是否是工作日
     *
     * @param calendar
     * @return
     * @throws Exception
     */
    public boolean isWorkday(String calendar) throws Exception {
        //程序启动后用的时候取出来  每次重新启动后在取

        if(lawHolidays.size()<=0){
            ChineseCalendaInfo chineseCalendar2 = new ChineseCalendaInfo();
           // List<ChineseCalendaInfo> list = chineseCalendar.chineseCalendaInfoService.selectChineseCalendaInfo(chineseCalendar2);
            List<ChineseCalendaInfo> list = chineseCalendaInfoService.selectChineseCalendaInfo(chineseCalendar2);
            for (int i = 0; i < list.size( ); i++) {
                lawHolidays.add(list.get(i).getLegalDate( ));
                extraWorkdays.add(list.get(i).getExtraWorkDate( ));
            }
        }
        this.isMatchDateFormat(calendar);
        return !(this.isHoliday(calendar));
    }



    public int getTotalDays() {
        return new GregorianCalendar( ).isLeapYear(Calendar.YEAR) ? 366 : 365;
    }

    public int getTotalLawHolidays() {
        return lawHolidays.size( );
    }

    public int getTotalExtraWorkdays() {
        return extraWorkdays.size( );
    }

    /**
     * 获取一年中所有周末的天数
     *
     * @return
     */
    public int getTotalWeekends() {
        List<String> saturdays = new ArrayList<String>( );
        List<String> sundays = new ArrayList<String>( );
        Calendar calendar = Calendar.getInstance( );
        int currentYear = calendar.get(Calendar.YEAR);
        int nextYear = 1 + calendar.get(Calendar.YEAR);
        Calendar cstart = Calendar.getInstance( );
        Calendar cend = Calendar.getInstance( );
        cstart.set(currentYear, 0, 1);// 今年的元旦
        cend.set(nextYear, 0, 1);// 明年的元旦
        return this.getTotalSaturdays(saturdays, calendar, cstart, cend,
                currentYear)
                + this.getTotalSundays(sundays, calendar, cstart, cend,
                currentYear);
    }

    private int getTotalSaturdays(List<String> saturdays, Calendar calendar,
                                  Calendar cstart, Calendar cend, int currentYear) {
        // 将日期设置到上个周六
        calendar.add(Calendar.DAY_OF_MONTH, -calendar.get(Calendar.DAY_OF_WEEK));
        // 从上周六往这一年的元旦开始遍历，定位到去年最后一个周六
        while (calendar.get(Calendar.YEAR) == currentYear) {
            calendar.add(Calendar.DAY_OF_YEAR, -7);
        }
        // 将日期定位到今年第一个周六
        calendar.add(Calendar.DAY_OF_YEAR, 7);
        // 从本年第一个周六往下一年的元旦开始遍历
        for (; calendar.before(cend); calendar.add(Calendar.DAY_OF_YEAR, 7)) {
            saturdays.add(calendar.get(Calendar.YEAR) + "-"
                    + calendar.get(Calendar.MONTH) + "-"
                    + calendar.get(Calendar.DATE));
        }
        return saturdays.size( );
    }

    private int getTotalSundays(List<String> sundays, Calendar calendar,
                                Calendar cstart, Calendar cend, int currentYear) {
        // 将日期设置到上个周日
        calendar.add(Calendar.DAY_OF_MONTH,
                -calendar.get(Calendar.DAY_OF_WEEK) + 1);
        // 从上周日往这一年的元旦开始遍历，定位到去年最后一个周日
        while (calendar.get(Calendar.YEAR) == currentYear) {
            calendar.add(Calendar.DAY_OF_YEAR, -7);
        }
        // 将日期定位到今年第一个周日
        calendar.add(Calendar.DAY_OF_YEAR, 7);
        // 从本年第一个周日往下一年的元旦开始遍历
        for (; calendar.before(cend); calendar.add(Calendar.DAY_OF_YEAR, 7)) {
            sundays.add(calendar.get(Calendar.YEAR) + "-"
                    + calendar.get(Calendar.MONTH) + "-"
                    + calendar.get(Calendar.DATE));
        }
        return sundays.size( );
    }

    public int getTotalHolidays() {
        //先获取不需要补班的周末天数
        int noWorkWeekends = this.getTotalWeekends( ) - this.getTotalExtraWorkdays( );
        return noWorkWeekends + this.getTotalLawHolidays( );
    }

    /**
     * 使用正则表达式匹配日期格式
     *
     * @throws Exception
     */
    private void isMatchDateFormat(String calendar) throws Exception {
        Pattern pattern = Pattern.compile("\\d{4}-\\d{2}-\\d{2}");
        Matcher matcher = pattern.matcher(calendar);
        boolean flag = matcher.matches( );
        if (!flag) {
            throw new Exception("输入日期格式不正确，应该为2017-02-03");
        }
    }

    public static void main(String[] args) throws Exception {
        String calendar = "2018-10-02";
        ChineseCalendar cc = new ChineseCalendar( );
        System.out.println("是否是法定节假日：" + cc.isLawHoliday(calendar));
        System.out.println("是否是周末：" + cc.isWeekends(calendar));
        System.out.println("是否是需要额外补班的周末：" + cc.isExtraWorkday(calendar));
        System.out.println("是否是休息日：" + cc.isHoliday(calendar));
        System.out.println("是否是工作日：" + cc.isWorkday(calendar));
        System.out.println("今年总共有" + cc.getTotalDays( ) + "天");
        System.out.println("今年总共有" + cc.getTotalLawHolidays( ) + "天法定节假日");
        System.out.println("今年总共有" + cc.getTotalExtraWorkdays( ) + "天需要补班的周末");
        System.out.println("今年总共有" + cc.getTotalWeekends( ) + "天周末");
        System.out.println("今年总共有" + cc.getTotalHolidays( ) + "天休息日");
    }


}
